﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FgoDataCrawler.Entity;
using FgoDataCrawler.Message.LeaderBoard;
using NPOI.OpenXmlFormats.Spreadsheet;

namespace FgoDataCrawler
{
    using LeaderBoardMessage = FgoDataCrawler.Message.LeaderBoard.LeaderBoard;
    using LeaderBoardEntity = FgoDataCrawler.Entity.AppMedia.LeaderBoard;

    public class LeaderBoardGenerator
    {
        private static Dictionary<int, List<int>> _idMapper;
        private static Dictionary<int, string> _avatarMapper;

        private static Dictionary<int, List<int>> IdMapper
        {
            get
            {
                if (_idMapper == null)
                {
                    _idMapper = new Dictionary<int, List<int>>();
                    // 从文件加载
                    var lines = File.ReadAllLines(@"D:\temp\idmap.csv");
                    foreach (var line in lines)
                    {
                        var ids = line.Split(',');
                        var servantId = Int32.Parse(ids[0]);
                        var appmediaId = Int32.Parse(ids[1]);
                        if (!_idMapper.ContainsKey(appmediaId))
                        {
                            _idMapper[appmediaId] = new List<int>();
                        }
                        _idMapper[appmediaId].Add(servantId);
                    }
                }
                return _idMapper;
            }
        }

        private static Dictionary<int, string> AvatarMapper
        {
            get
            {
                if (_avatarMapper == null)
                {
                    _avatarMapper = new Dictionary<int, string>();
                    // 从文件加载
                    var lines = File.ReadAllLines(@"D:\temp\avatars.csv");
                    foreach (var line in lines)
                    {
                        var ids = line.Split(',');
                        var servantId = Int32.Parse(ids[0]);
                        var avatarUrl = ids[1];
                        _avatarMapper[servantId] = avatarUrl;
                    }
                }
                return _avatarMapper;
            }
        }

        public static LeaderBoardMessage Generate(LeaderBoardEntity entity)
        {
            LeaderBoardMessage lboard = new LeaderBoardMessage();

            string rare = "";
            switch (entity.Rare)
            {
                case 5:
                    rare = "五";
                    break;
                case 4:
                    rare = "四";
                    break;
                case 3:
                    rare = "三";
                    break;
                case 2:
                    rare = "二";
                    break;
                case 1:
                    rare = "一";
                    break;
                case 0:
                    rare = "无";
                    break;
            }

            string updateTime = "2018-04-11";  // DateTime.Now.ToString("YYYY-mm-dd");
            lboard.Title = string.Format("Appmedia最强{0}星排行榜  {1}", rare, updateTime);
            lboard.Ranks = new List<Rank>();
            var ranks = from mark in entity.Marks group mark by mark.Rank;

            foreach (var rank in ranks)
            {
                Rank rankMsg = new Rank();

                string desc = "";
                if (entity.Rare == 5)
                {
                    switch (rank.Key)
                    {
                        case "SS":
                            desc = "环境";
                            break;
                        case "S+":
                            desc = "最上位";
                            break;
                        case "S":
                            desc = "上位";
                            break;
                        case "A":
                            desc = "中坚";
                            break;
                        case "B":
                            desc = "下位";
                            break;
                        case "C":
                            desc = "希望强化";
                            break;
                        default:
                            desc = "其他";
                            break;
                    }
                }
                rankMsg.Name = string.Format("▼{0}级别▼{1}", rank.Key, desc);

                rankMsg.Groups = new List<Group>();
                var smgroups = from sm in rank.ToList() group sm by sm.Score;
                foreach (var smgroup in smgroups)
                {
                    Group groupMsg = new Group();

                    var score = smgroup.Key;
                    groupMsg.Score = score;

                    groupMsg.Servants = new List<Servant>();
                    foreach (var servant in smgroup)
                    {
                        if (!IdMapper.ContainsKey(servant.AppMediaId)) continue;
                        
                        var ids = IdMapper[servant.AppMediaId];
                        foreach (var id in ids)
                        {
                            if (!AvatarMapper.ContainsKey(id)) continue;

                            Servant servantMsg = new Servant();
                            servantMsg.Id = id;
                            servantMsg.Name = servant.Name;
                            servantMsg.AvatarUrl = AvatarMapper[id];

                            groupMsg.Servants.Add(servantMsg);
                        }
                    }

                    rankMsg.Groups.Add(groupMsg);
                }

                lboard.Ranks.Add(rankMsg);
            }

            // 排序，填色
            int index = 0;
            int amount = lboard.GroupCount;
            foreach (var rank in lboard.Ranks)
            {
                foreach (var group in rank.Groups)
                {
                    string color = GetColor(index++, amount);
                    group.Color = color;
                }
            }

            return lboard;
        }

        public static string GetColor(int index, int amount)
        {
            double p = index*1.0/(amount-1);
            int r=0, g=0, b=0;

            if (p<=0.25)
            {
                r = 0xff;
                b = 0;
                g = (int)(0xff * ((p - 0) / 0.25));
            }
            else if (p>0.25 && p<=0.5)
            {
                g = 0xff;
                b = 0;
                r = (int)(0xff * (1-((p - 0.25) / 0.25)));
            }
            else if (p > 0.5 && p <= 0.75)
            {
                r = 0;
                g = 0xff;
                b = (int)(0xff * ((p - 0.5) / 0.25));
            }
            else
            {
                r = 0;
                b = 0xff;
                g = (int)(0xff * (1-((p - 0.75) / 0.25)));
            }

            int rgb = (r << 16) | (g << 8) | b;
            return string.Format("#{0:X6}", rgb);
        }
    }
}
